package com.user.controller.Campus;


import DTO.UserLoginDTO;
import com.user.service.UserService;
import com.utils.JwtUtils;
import com.utils.Sample;
import constant.CodeConstant;
import constant.MsgConstant;
import constant.RedisPreKeyConstant;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import result.Result;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/campus/user")
public class LoginController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserService userService;


    /**
     * 根据手机号获取验证码
     * 返回状态码
     *      102 - 电话号码不正确
     *      10  - 重复获取验证码
     *      200 - 获取成功
     * @param phoneNumber 用户手机号
     * @return 无
     */
    @GetMapping("/getCodeByPhoneNum")
    public Result<String> getCodeByPhoneNum(@RequestParam String phoneNumber){

        // 参数检查
        if (!Sample.isPhoneNumber(phoneNumber)){
            return Result.error(MsgConstant.PHONE_NUMBER_NOT_RIGHT,CodeConstant.PHONE_NUMBER_NOT_RIGHT);
        }

        // redis中 key 键 值的设置为code + 每个人的手机号
        String key = RedisPreKeyConstant.USER_LOGIN + phoneNumber;

        // 1.1 先获取redis中有无该key的值，如果有则不能给前端返回新的验证码
        String redis_code = stringRedisTemplate.opsForValue().get(key);
        if (redis_code!=null){
            // 1.2 表示redis中有这个验证码
            return Result.error(MsgConstant.REPEATEDLY_GET_CODE, CodeConstant.REPEATEDLY_GET_CODE);
        }

        // 2. 随机生成验证码四位数
        String code = Sample.generateFourDigitVerificationCode();
        stringRedisTemplate.opsForValue().set(key,code);

        // 3. 设置保存时间为3分钟
        long expirationTimeInSeconds = 60* 3L;
        stringRedisTemplate.expire(key, expirationTimeInSeconds, TimeUnit.SECONDS);

        // 4.发送验证码
        try {
            Sample.sendSms(phoneNumber,code);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success();
    }


    /**
     * 用户登录
     * 当该用户为在数据库时，自动对该用户进行注册
     * 当type = 0的时候表示验证码登录
     * 当type = 1的时候表示密码登录
     * 返回状态码
     *      101 - 手机号不正确
     *      103 - 参数不满足要求，也就是type不是1或者0
     *      11  - 验证码过期了
     *      12  - 验证码不正确
     *      13  - 密码不正确
     *      14  - 该用户不存在
     *      200 - 登录成功
     * @param userLoginDTO 用户提交的数据
     * @return token
     */
    @PostMapping("/login")
    public Result<String> login(@RequestBody UserLoginDTO userLoginDTO){
        // 1.手机号检查
        if (userLoginDTO.getPhoneNumber() == null || userLoginDTO.getPhoneNumber().isEmpty()){
            // 表示用户手机号并没有输入，有可能是渗透攻击，直接将其返回
            return Result.error(MsgConstant.LACK_PARAM,CodeConstant.LACK_PARAM);
        }

        // 2. 判断登录方式
        if (userLoginDTO.getType() == 1){
            // 2.1 密码登录,密码错误 0，该手机号未注册 -1，正确 用户id
            Integer passwordType = userService.LoginByPassword(userLoginDTO);

            if (passwordType == 0){
                // 密码错误
                return Result.error(MsgConstant.PASSWORD_NOT_RIGHT,CodeConstant.PASSWORD_NOT_RIGHT);
            } else if (passwordType == -1) {
                // 没有找到该用户
                return Result.error(MsgConstant.USER_NOT_EXIST,CodeConstant.USER_NOT_EXIST);
            } else if (passwordType > 0) {
                // 密码正确，生成token返回给前端
                Map map = new HashMap();
                map.put("id",passwordType);
                String token = JwtUtils.generateJwt(map);
                return Result.success(token);
            }
        } else if (userLoginDTO.getType() == 0) {
            // 2.2 验证码登录
            String key = RedisPreKeyConstant.USER_LOGIN + userLoginDTO.getPhoneNumber();
            String redis_code = stringRedisTemplate.opsForValue().get(key);

            if (redis_code==null){
                // 2.2.3 表示验证码已经过期了，需要重新获取验证码
                return Result.error(MsgConstant.CODE_EXPIRATION,CodeConstant.CODE_EXPIRATION);
            }else if (!redis_code.equals(userLoginDTO.getCode())) {
                // 2.2.3 表示验证码不正确
                return Result.error(MsgConstant.CODE_NOT_RIGHT,CodeConstant.CODE_NOT_RIGHT);
            }

            // 2.3 满足验证码，进行token生成
            Map map = new HashMap();
            map.put("id",userService.userRegistered(userLoginDTO));
            String token = JwtUtils.generateJwt(map);
            return Result.success(token);
        }

        // 3. 当这个type不是0或者1的时候，表示前端错误的传递参数
        return Result.error(MsgConstant.PARAM_NOT_SATISFY,CodeConstant.PARAM_NOT_SATISFY);
    }


    /**
     * 获取用户头像
     * 方便前端使用 TODO 后面在进行修改
     * @param userId 用户id
     * @return
     */
    @GetMapping(value = "/avatars/{userId}", produces = MediaType.IMAGE_JPEG_VALUE)
    public ResponseEntity<byte[]> getAvatar(@PathVariable String userId) {
        try {
            // 假设userService.getAvatar(userId)返回的是图片文件的本地相对路径
            String avatarPath = userService.getAvatar(userId);

            // 将相对路径转换为绝对路径
            Path path = Paths.get(avatarPath);
            Resource resource = new FileSystemResource(path.toFile());

            if (resource.exists() && resource.isReadable()) {
                // 读取文件内容到字节数组
                byte[] avatarBytes = Files.readAllBytes(path);

                // 返回包含图片字节数据的ResponseEntity
                return ResponseEntity.ok()
                        .contentType(MediaType.IMAGE_JPEG)
                        .body(avatarBytes);
            } else {
                // 如果没有找到头像或者不可读，返回404 Not Found
                return ResponseEntity.notFound().build();
            }
        } catch (IOException e) {
            // 处理文件读取异常，返回500 Internal Server Error或其他状态码
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}
